#include "Inf_CPS121.h"

/**
 * @brief 初始化 CPS121-700
 *
 */
void Inf_CPS121_Init(void)
{
    /* 初始化I2C */
    Driver_I2C_Init();
}

/**
 * @brief MR指令, 唤醒传感器，并将测量结果存在内部传感器
 *
 * @return Status_t 状态码
 */
Status_t Inf_CPS121_MRCmd(void)
{

    /* 1. 发送起始信号 */
    Driver_I2C_Start();

    /* 2. 发送从机地址 */
    Driver_I2C_SendByte(CPS121_WRITE_ADDR);
    if (Driver_I2C_Wait4Ack() == NACK) {
        Driver_I2C_Stop();
        return STATUS_FAIL;
    }

    /* 3. 发送寄存器地址 */
    Driver_I2C_SendByte(CPS121_MR_REG_ADDR);
    if (Driver_I2C_Wait4Ack() == NACK) {
        Driver_I2C_Stop();
        return STATUS_FAIL;
    }

    /* 4. 发送测量指令 */
    Driver_I2C_SendByte(CPS121_MR_CMD);
    if (Driver_I2C_Wait4Ack() == NACK) {
        Driver_I2C_Stop();
        return STATUS_FAIL;
    }

    /* 5. 发送结束信号 */
    Driver_I2C_Stop();

/* 6. 延时5ms以上等待转换完成 */
#if FreeRTOS
    vTaskDelay(6);
#else
    FL_DelayMs(6);
#endif

    return STATUS_OK;
}

/**
 * @brief 发送GD指令, 获取寄存器中的压力数据
 *
 * @param originalPressure 寄存器中原始的压力数据
 * @return Status_t        状态码
 */
Status_t Inf_CPS121_GDCmd(uint32_t *originalPressure)
{

    /* 1. 发送起始信号 */
    Driver_I2C_Start();

    /* 2. 发送从机地址 */
    Driver_I2C_SendByte(CPS121_WRITE_ADDR);
    if (Driver_I2C_Wait4Ack() == NACK) {
        Driver_I2C_Stop();
        return STATUS_FAIL;
    }

    /* 3. 发送寄存器地址 */
    Driver_I2C_SendByte(CPS121_GD_REG_ADDR);
    if (Driver_I2C_Wait4Ack() == NACK) {
        Driver_I2C_Stop();
        return STATUS_FAIL;
    }

    /* 4. 发送起始信号 */
    Driver_I2C_Start();

    /* 5. 发送从机读地址 */
    Driver_I2C_SendByte(CPS121_READ_ADDR);
    if (Driver_I2C_Wait4Ack() == NACK) {
        Driver_I2C_Stop();
        return STATUS_FAIL;
    }

    /* 6. 读取数据 */
    uint32_t pressure = 0;
    pressure          = (uint32_t)Driver_I2C_ReceiveByte() << 16; // 第一个字节 [23:16]
    Driver_I2C_Ack();

    pressure |= (uint32_t)Driver_I2C_ReceiveByte() << 8;          // 第二个字节 [15:8]
    Driver_I2C_Ack();

    pressure |= (uint32_t)Driver_I2C_ReceiveByte();               // 第三个字节 [7:0]
    Driver_I2C_Nack();

    /* 7. 发送结束信号 */
    Driver_I2C_Stop();

    *originalPressure = pressure;

    return STATUS_OK;
}

/**
 * @brief 将寄存器中原始的压力值转换成真实世界的压力值
 *
 * @param originalPressure  寄存器中原始的压力数据
 * @return uint32_t         转换后真实的压力值(KPa)
 */
uint32_t Inf_CPS121_ConvertRealPressure(uint32_t originalPressure)
{
    uint8_t byte3 = (originalPressure >> 16) & 0xFF; // [23:16]
    uint8_t byte2 = (originalPressure >> 8) & 0xFF;  // [15:8]
    uint8_t byte1 = originalPressure & 0xFF;         // [7:0]

    uint32_t realPressure = (uint32_t)(byte3 * 65536 + byte2 * 256 + byte1) / 8 / 1000;

    return realPressure;
}

/**
 * @brief 选择压力传感器芯片
 *
 * @param sensor SENSOR_CPS121_1、SENSOR_CPS121_2、SENSOR_CPS121_3
 */
void Inf_CPS121_SelectSensor(SelCPS121Sensor_t sensor)
{
    switch (sensor) {
    case SENSOR_CPS121_1: Driver_I2C_SelectSCLx(SCLx_1); break;
    case SENSOR_CPS121_2: Driver_I2C_SelectSCLx(SCLx_2); break;
    case SENSOR_CPS121_3: Driver_I2C_SelectSCLx(SCLx_3);
    }
}

/**
 * @brief 直接读取当前气压的值, 将转换和读取的操作封装在一起
 *
 * @param airPressureNum    气压传感器的编号
 * @return uint32_t         转换后的气压值KPa
 */
uint32_t Inf_CPS121_ReadCurrentPressure(AirPressureNum_t airPressureNum)
{
    if (airPressureNum > AIR_PRESSURE_NUM_RIGHT) {
        LOG("airPressureNum error\n");
        return 0;
    }

    /* 选择气压传感器 */
    switch (airPressureNum) {
    case AIR_PRESSURE_NUM_BAROMETRIC_PRESSURE: Inf_CPS121_SelectSensor(SENSOR_CPS121_1); break;
    case AIR_PRESSURE_NUM_LEFT:                Inf_CPS121_SelectSensor(SENSOR_CPS121_2); break;
    case AIR_PRESSURE_NUM_RIGHT:               Inf_CPS121_SelectSensor(SENSOR_CPS121_3); break;
    }

    /* MR */
    if (Inf_CPS121_MRCmd() != STATUS_OK) {
        LOG("MR error\n");
    }

    uint32_t originalPressure = 0; /* 存储实际测量的气压值 */

    /* GD */
    if (Inf_CPS121_GDCmd(&originalPressure) != STATUS_OK) {
        LOG("GD error\n");
    }

    /* 转换成实际压力 */
    uint32_t realPressure = Inf_CPS121_ConvertRealPressure(originalPressure);

    return realPressure;
}
